home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 November / macformat-030.iso / Shareware City / Developers / FANTASM V3.16 unreg / Readme files / Traps explained < prev   
Encoding:
Text File  |  1995-06-25  |  9.9 KB  |  225 lines  |  [TEXT/R*ch]

  1. The following is an extract from a reply I wrote to a Mac programming forum during 
  2. the development of Fantasm V2. Whilst V3 has global include files for traps and system
  3. variables, the chat below still explains nicely what a Mac trap is, and how you can find out
  4. which trap you need. The header files mentioned below are included on Fantasm V3.xx
  5. disk #4.
  6. ------------------------------------------------------------------------------------
  7.   
  8. Traps - right, on a 68k you have 16 hardware traps - 0 to 15.
  9. On a Mac, operating system calls are also called TRAPS, just to confuse
  10. machine code programmers!!!!
  11.  
  12. So, any call to the OS, in Mac parlance is a trap.
  13. Traps work by defining a special 68K illegal instruction. All 68K instruction
  14. op codes are 16 bits - for example $4e75 is the 68K instruction for RTS.
  15.  
  16. So, in assembler, you could either write RTS or dc.w $4e75 - its the same thing.
  17. Of course RTS is much easier to remember than $4e75, thats why we have assemblers!
  18.  
  19. Any instruction along the lines of $Axxx causes the 68k to jump through the
  20. "line a vector" to a software routine that implements this instruction. If you
  21. like its a way of synthesising instructions, or extending the processors instruction
  22. set through software.
  23. The routine at the line a vector examines the instruction, then jumps to 
  24. the right routine to handle it.
  25. So for example if we dc.w $a982 (close dialog), when the 68K jumps to the line a vector,
  26. the code there examines the instruction, says "Oh yeah, close dialog" and jumps to
  27. the software that closes a dialog box.
  28.  
  29. Of course, some "traps" need parameters - these are normally passed on the stack.
  30. Consider:
  31. closedialog:    equ    $a982    *define close dialog trap
  32.     .....        *open dialog 
  33.     ......        *and processing
  34.     .....
  35. **now close the dialog box
  36.     move.l    dialog_handle(pc),-(sp)    *pass the dialogs handle
  37.     dc.w    closedialog        *close dialog "trap"
  38.     rts
  39.     
  40. (BTW, the amount of typing involved in the above code is far less than the equivalent
  41. C code, and without remembering the semicolons, brackets, squigily brackets and
  42. other C nause!)
  43. Sometimes however, the parameters are passed in 68K registers, although these
  44. are few on the ground, and sometimes, as in the shutdown example, in data regs and
  45. on the stack - what I call a voodoo trap, perform some magical incantations over
  46. the keyboard until it works,basically!, but I'm sure apple have a more scientific
  47. explanation - (or maybe not) :-)
  48.  
  49. To define a trap, you need to insert the trap word into the code. We do this with
  50. the DC directive. As all traps definitions are words, we use DC.W. Its also far more
  51. readable to equate the trap numbers to their real names, rather than just using the
  52. numbers (as I did in the quick and dirty shutdown example! But its ok, 
  53. I'm a professional?!?!)
  54.  
  55. Anyway, as some registered users of fantasm have pointed out, where do you find
  56. out these (sometimes obscure) trap calls, they werent included in the package!
  57.  
  58. Well they are available as the C header files for the MPW (Macintosh Programmers Workshop
  59. - *NOT* Macintosh Programmers Workbench as stated in a rather popular Mac magazine this
  60. month) developers system. They may still be available on Apple Crackers. If anybody 
  61. has problems obtaining these files, they may magically appear on Portland and Cosmos,
  62. although dont ask me how :-)
  63.  
  64. What you get is 780K of header files for all current mac OS traps, sometimes called
  65. Toolbox traps. As a simple example, of first a trap that uses registers,
  66. lets assume we want to get 30k of memory from the system, to use as a buffer.
  67. We look up the header files, and in the MEMORY file we find:
  68.  
  69. #pragma parameter __A0 NewPtr(__D0)
  70. pascal Ptr NewPtr(Size byteCount)
  71.     = 0xA11E; 
  72.  
  73. This tells use the trap name is NewPtr. We think, yes, we want a new pointer to a buffer,
  74. so that'll probably do. Next we need know what parameters we need.
  75. Well, we see "pascal Ptr NewPtr(Size bytecount)". This is how to call the trap from
  76. pascal. From this we can determine that the trap needs a parameter called byteCount
  77. and it returns a pointer.
  78. Now to translate that into machine code, the line:
  79.  
  80. #pragma parameter __A0 NewPtr(__D0)
  81.  
  82. Tells use that the input paramter goes in d0, and the trap returns the new pointer
  83. in a0.
  84. Finally, the bottom line, = 0xA11E, gives use the actual trap number.
  85.  
  86. To summarise, the number of bytes we want goes in d0, the trap returns the address
  87. of the start of the block (the pointer) in A0 and the trap number is $a11e.
  88. So:
  89. newptr:    equ    $a11e
  90.  
  91. getmybuffer:    move.l    #30*1024,d0    the input parameter is 30kbytes
  92.     dc.w    newptr    do newptr trap
  93.     move.l    a0,mybufferaddress(a6)
  94.     rts
  95. mybufferaddress now contains the start address of a 30K block of memory you can use.
  96.  
  97. NOTE, if a trap cant be completed, and error will be returned, in this case in d0
  98. with a0 being zero.
  99. The errors are normally negative numbers, and are listed in the header files as 
  100. "errors.h". So a more realistic routine would be:
  101.  
  102. newptr:    equ    $a11e    *equates normally live in an include file!
  103.  
  104. getmybuffer:    move.l    #30*1024,d0    *we want 30K
  105.     dc.w    newptr    *get it from allocated memory
  106.     tst.l    a0    *check for error
  107.     beq    error    *system couldnt allocate memory!
  108.     move.l    a0,mybufferaddress(a6)    *save pointer
  109.     rts
  110.     
  111. **SNIPPET - nearly all memory traps use registers, normally d0 for the input parameter
  112. and a0 for the return parameter**
  113.  
  114. **BIG TIP - Mac memory management is nothing to write home about, using newptr to
  115. define every block of memory you need is very slow. The best way is too grab all
  116. free memory, with the MAXMEM trap, then use your own routines to allocate memory 
  117. from that big block - registered users of fantasm will be given the details on request**
  118.  
  119. Ok, now a stack based trap, hang on, just make a cup of coffee....Ahh NescafĂ©...
  120. (Sorry, but I've always wanted to use one of those e things)
  121.  
  122. Normally, the mac OR's characters onto the screen when you are printing, this
  123. is fine, until you want to overwrite some text in a window. 
  124. For example, suppose we have a counter on the screen in the bottom right. The counter 
  125. starts a 0, then 1 and so on. First the 0 is printed, next the 1, but because 
  126. the Mac is oring the characters on the screen, the 1 is mixed in with the 0!
  127. One way to get round this is delete the 0 first - somehow, the other way is to
  128. set the Mac to overwrite characters, instead of oring them.
  129.  
  130. In the quickdraw headers file, there is a trap to set the screen writing mode - 
  131.  
  132. pascal void TextMode(short mode)
  133.     = 0xA889; 
  134. We can see, the parameter is defined a "short mode", well short means word, and as
  135. there are no registers defined, it must go on the stack. Mode can be numerous values,
  136. but the two we're interested in here is 1=OR drawing mode, and 0=replace drawing mode.
  137. The word "void" means the trap returns nothing.
  138. So:
  139. TEXT_MODE:    EQU    $A889
  140.  
  141.     MOVE.W    #1,-(A7) ;    *OR DRAWING MODE
  142.     DC.W    TEXT_MODE
  143.  
  144.     MOVE.W    #0,-(A7)
  145.     DC.W    TEXT_MODE ;    *REPLACE DRAWING MODE
  146.  
  147. Now lets look at a trap that returns a parameter on the stack:
  148.  
  149. pascal short OpenResFile(ConstStr255Param fileName)
  150.     = 0xA997; 
  151.  
  152. pascal void UseResFile(short refNum)
  153.     = 0xA998; 
  154.  
  155. Openresfile returns a refnum to the resource fork of a file. Suppose you wanted
  156. your application to read one of its resources into memory. First thing you have to do is
  157. tell the mac which resource file to use, so by reference to the above two trap
  158. definitions:
  159.  
  160. openresfile:    equ    $a997
  161. useresfile:    equ    $a998
  162.  
  163. open_my_res:    pea    my_filename    *push our filename onto the stack
  164.     dc.w    openresfile    *open our resource fork
  165.     move.w    (sp)+,res_refnum    *save our refnum
  166.     
  167.     move.w    res_refnum,-(sp)    
  168.     dc.w    useresfile
  169.     rts
  170. my_filename:    dc.b    9,"stus_file"    *our filename in pascal format
  171.     even
  172. res_refnum:    ds.w    1    *space for refnum
  173.  
  174. Firstly, note this code segment is written in position dependant code, for 
  175. simplicity. Secondly, notice that the filename is given in Pascal format.
  176. Users of Fantasm V3.xx can use the C_TO_P library functione to convert a C string
  177. "Stus_file",0 to a pascal string. 
  178. Thirdly, notice the way the return parameter from openresfile is "POPPED"
  179. off the stack, using the post increment addressing mode, thus getting the return
  180. parameter *and* tidying up the stack.
  181.  
  182.  
  183. Ok, so considering the above, lets look at the shutdown code:
  184.  
  185. pascal void ShutDwnPower(void)
  186.     = {0x3F3C,0x0001,0xA895}; 
  187.     
  188. This unfortunately, gives us no clues whatsoever! If somebody can explain how a compiler
  189. can translate this, then please let me know!
  190.  
  191. I translated it by stepping through the shutdown trap in Macsbug, to find out what it 
  192. expected, and this is what I came up with, maybe somebody with Inside Mac can explain?
  193. Anyway, this is my interpretation:
  194.  
  195. pascal void ShutDwnPower(void)
  196.     = {0x3F3C,    0x0001,  0xA895}; 
  197. Shutdown |            |       |
  198. 1=shutdown, 2=restart |       |
  199. The trap number               |
  200.  
  201. shutdown:    Move.w #1,-(sp)     1=shutdown, 2=restart
  202.     move.l #$3f3c,d0    Shutdown, as A895 is used for other shutdown procedures.
  203.     dc.w $a895        trap number.
  204.     rts
  205.  
  206. As you can see from this one, sometimes a trap number is used for more than one specific
  207. function, so additional qualifiers are needed - the 3f3c for example.
  208.  
  209. Hope this explains how to translate header files a little Dave.
  210. You are quite right about the diskeject trap, needing a parameter block. The PB
  211. in question is as detailed in the Fantasm beginners guide - i.e .the Mac has to know
  212. which disk specifically to eject, so the PB is important, as the Mac could be on
  213. a network! :-)
  214. BTW, you wont harm your HD by ejecting it accidentally whilst experimenting (been
  215. there, done that etc), but I never said that, if you (or anybody else) trashes their 
  216. HD!
  217.  
  218. ------------------------------------------------------------------------------------
  219. For Fantasm V3.xx, there is no need to equate the trap numbers. They've all been
  220. done for you in the file Mac_traps.s in the standard includes folder on disk 1 
  221. (registered versions only!) All
  222. you ned do is copy these include files into your project global includes file, then you
  223. can use the trap names without equating them first. Note that all the trap names
  224. are preceded by the underscore character.
  225.